package org.vaadin.passwordfield.client.ui;

import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.UIDL;
import com.vaadin.terminal.gwt.client.ui.VOverlay;

public class VPasswordField extends
        com.vaadin.terminal.gwt.client.ui.VPasswordField {

    private static final VOverlay clwoverlay = new VOverlay(true, false, false);
    private static final Image clwcontent = new Image();
    private String clwmsg;
    private String clwicon;

    private static final VOverlay choverlay = new VOverlay(false, false, true);
    private static final HTML chcontent = new HTML();
    private String chdesc;
    private Timer chshowtimer;
    private Timer chhidetimer;

    public VPasswordField() {
        clwoverlay.setStyleName("capslockwarning");
        clwoverlay.setWidget(clwcontent);
        clwoverlay.setAnimationEnabled(true);

        choverlay.setWidget(chcontent);
        choverlay.setAnimationEnabled(true);
        chshowtimer = new Timer() {
            @Override
            public void run() {
                int len = getText().length();
                if (!clwoverlay.isShowing() && len > 3) {

                    String[] c = PasswordFieldUtils.hashColors(getText());
                    int h = getOffsetHeight() - 4;
                    int w = h / 3;

                    String html = "";
                    for (int i = 0; i < 3; i++) {
                        html += "<div style=\"background-color:" + c[i]
                                + ";float:left;height:" + h + "px;width:" + w
                                + "px;\"></div>";
                    }
                    chcontent.setPixelSize(h, h);
                    chcontent.setHTML(html);
                    choverlay.setTitle(chdesc);
                    choverlay.setPopupPositionAndShow(new MyPositionCallback(
                            choverlay));
                    chhidetimer.schedule(2000);
                }
            }
        };
        chhidetimer = new Timer() {
            @Override
            public void run() {
                choverlay.hide();
            }
        };

        addKeyPressHandler(new KeyPressHandler() {
            public void onKeyPress(KeyPressEvent event) {
                chshowtimer.cancel();
                char ch = event.getCharCode();
                if (clwmsg != null
                        && (Character.isUpperCase(ch) && !event
                                .isShiftKeyDown())
                        || (Character.isLowerCase(ch) && event.isShiftKeyDown())) {
                    clwoverlay.setTitle(clwmsg);
                    clwcontent.setUrl(clwicon);
                    clwoverlay.setPopupPositionAndShow(new MyPositionCallback(
                            clwoverlay));
                } else {
                    clwoverlay.hide();
                }
                if (chdesc != null) {
                    chshowtimer.schedule(500);
                }
            }
        });
        addFocusHandler(new FocusHandler() {
            public void onFocus(FocusEvent event) {
                clwoverlay.hide();
            }
        });
    }

    /**
     * Called whenever an update is received from the server
     */
    public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
        super.updateFromUIDL(uidl, client);
        if (uidl.hasAttribute("capswarning")) {
            clwmsg = uidl.getStringAttribute("capswarning");
        } else {
            clwmsg = null;
        }
        if (uidl.hasAttribute("clwicon")) {
            clwicon = uidl.getStringAttribute("clwicon");
        }
        if (uidl.hasAttribute("flagdesc")) {
            chdesc = uidl.getStringAttribute("flagdesc");
        } else {
            chdesc = null;
        }
    }

    @Override
    protected void onDetach() {
        super.onDetach();
        clwoverlay.hide();
        choverlay.hide();
        chshowtimer.cancel();
        chhidetimer.cancel();
    }

    private class MyPositionCallback implements PositionCallback {
        private VOverlay target;

        MyPositionCallback(VOverlay target) {
            this.target = target;
        }

        public void setPosition(int offsetWidth, int offsetHeight) {
            int halfIcon = offsetHeight / 2;
            int halfInput = getOffsetHeight() / 2;
            int top = getAbsoluteTop() + halfInput - halfIcon;
            int left = getAbsoluteLeft() + getOffsetWidth() - offsetWidth / 2;
            target.setPopupPosition(left, top);

        }
    }

}
